/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Copyright 2002-2003 by Mark Wolgemuth, All rights reserved.             */
/* Copyright 2002-2003 by Employease, Inc.  All rights reserved.           */
/*                                                                         */
/* Redistribution and use in source and binary forms, with or without      */
/* modification, are permitted provided that the following conditions      */
/* are met:                                                                */
/*                                                                         */
/*    1. Redistributions of source code must retain the above copyright    */
/* notice, this list of conditions and the following disclaimer.           */
/*    2. Redistributions in binary form must reproduce the above copyright */
/* notice, this list of conditions and the following disclaimer in the     */
/* documentation and/or other materials provided with the distribution.    */
/*                                                                         */
/* THIS SOFTWARE IS PROVIDED BY THE MOD_ATHENA PROJECT ``AS IS'' AND ANY   */
/* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE       */
/* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR      */
/* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR        */
/* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   */
/* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,     */
/* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR      */
/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY     */
/* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT            */
/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE   */
/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.    */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#ifndef ATHD_H
#define ATHD_H

#include <syslog.h>

#if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
#include "unixd.h"
#endif

#include "ath_lb.h"
#include "athd_types.h"
#include "serf_filters.h"
#include "apr_signal.h"

/* default configs */
#define ATHD_DEFAULT_CONFFILE  "/usr/local/etc/athenad.conf"
#define ATHD_DEFAULT_USER      "nobody"
#define ATHD_DEFAULT_PORT      9000
#define ATHD_DEFAULT_SOCKET    "/var/tmp/athd.sock"
#define ATHD_DEFAULT_SHELL     "/bin/sh"
#define ATHD_DEFAULT_SENDMAIL  "/usr/sbin/sendmail -t"
#define ATHD_DEFAULT_LOGFILE   "/tmp/athd.log"
#define ATHD_DEFAULT_LOGLOCK   "/tmp/.athd.log.lock"
#define ATHD_DEFAULT_LOGLVL    ATHD_INFO
#define ATHD_DEFAULT_PIDFILE   "/tmp/.athd.pid"
#define ATHD_DEFAULT_QLIMIT    50 /* request_q limit */
#define ATHD_DEFAULT_REQEXPIRE 60 /* seconds in queue */
#define ATHD_DEFAULT_FREQ      5
#define ATHD_DEFAULT_MAIL_SUBJECT "(no subject)"
#define ATHD_DEFAULT_MAIL_TO   "mark@eease.com"
#define ATHD_DEFAULT_MAIL_REPLYTO  "mark@node.to"
#define ATHD_DEFAULT_MAIL_BODY "(no body)"
#define ATHD_DEFAULT_STATS_PULSE 4 /* times per sec to update stats */
#define ATHD_STATS_PULSE_GRAIN 10 /* pulse resolution (PULSE/GRAIN) */
#define ATHD_JOB_PROTO_NAME    "ATHD_JOB_PROTO"
/* connection attempt canceled after #tries */
#define ATHD_REQ_GIVEUP        1 /* not really very helpful */
/* limit to connections to athena service */
#define ATHD_MAX_CONN          32
/* limit to inbound input to cmd handler */
#define ATHD_MAX_CMD_RECV      16384
#define ATHD_MAX_CMD_SEND      32768
#define ATHD_CMD_SEND_IOVEC     (ATHD_MAX_CMD_SEND / 512)
#define ATHD_BROKEN_PIPE_DIE   3

#define ATHD_CMD_PROMPT_BASE   PACKAGE "-" VERSION "> "
#define ATHD_CMD_SESSION_TIMEOUT 300
/* max age of clone_map_* (eg farm and phys state cache) */
#define ATHD_CMD_MAP_EXPIRE    (apr_time_from_sec(2)) 

#ifdef HAVE_GETPGRP
#define GET_PID()  getpgrp()
#define KILL_PID(i, s)  killpg(i, s)
#else
#define GET_PID()  getpid()
#define KILL_PID(i, s)  kill(i, s)
#endif

#define ATHD_STATUS_IS_FATAL(rv) ((! APR_STATUS_IS_SUCCESS(rv))		\
				  && (! APR_STATUS_IS_EAGAIN(rv))	\
				  && (rv != ATHD_BAD_KEEPALIVE)		\
				  && (! APR_STATUS_IS_ECONNREFUSED(rv)))

#define ATHD_CMD_IS_QUIT(c) (c == CTRL('d'))

#define RV_OK if (!rv) rv

/* generates static inited element of property name with func */
#define ATHD_CONF_PROP(propname, propfunction, parentname) \
   { propname, propfunction, parentname }    

/* version.c */
void             athd_print_version();

/* proc.c */
void             athd_proc_exit(int status);
void             athd_proc_shutdown(int sig);
apr_status_t     athd_proc_sig_str(const char *str);
apr_status_t     athd_proc_write_pidfile();
apr_status_t     athd_proc_read_pidfile();
int              athd_proc_pid_is_alive(int pid);

/* mail.c */
athd_mail *      athd_mail_create(apr_pool_t *pool);
void             athd_mail_destroy(athd_mail **msg);
apr_status_t     athd_mail_build_for_job(athd_job *job, athd_mail *msg);
char *           athd_mail_msg_to_text(athd_mail *msg);
apr_status_t     athd_mail_send(athd_conf *conf, athd_mail *msg);

/* serf_filters.c */
apr_status_t     athd_filter_header_host(apr_bucket_brigade *brigade,
					 serf_filter_t *filter,
					 apr_pool_t *pool);
apr_status_t     athd_filter_header_agent(apr_bucket_brigade *brigade,
					  serf_filter_t *filter,
					  apr_pool_t *pool);
apr_status_t     athd_filter_http_headers(apr_bucket_brigade *brigade,
					  serf_filter_t *filter,
					  apr_pool_t *pool);
apr_status_t     athd_filter_resp_len(apr_bucket_brigade *brigade, 
				      serf_filter_t *filter,
				      apr_pool_t *pool);

/* request.c */
athd_request *   athd_req_create(apr_pool_t *pool, athd_engine *eng, 
				     athd_req_type type, const void *data);
athd_request *   athd_req_create_for_job(athd_job *job, athd_engine *engine,
					 athd_req_type type, const void *data);
athd_request *   athd_req_serf_req_build(athd_request *req);
void             athd_req_destroy(athd_request **request);
apr_status_t     athd_req_handler_in(apr_bucket_brigade *brigade,
				     serf_request_t *request, apr_pool_t *pool);
apr_status_t     athd_req_handler_out(serf_response_t *response, 
				      apr_pool_t *pool);

/* job.c */
athd_job *       athd_job_create(apr_pool_t *pool, const char *name);
void             athd_job_destroy(athd_job **job);
void             athd_job_cache_init(apr_pool_t *pool);
athd_job *       athd_job_add_by_name(athd_conf *conf, const char *name);
athd_job *       athd_job_for_name(ath_list *jobs, const char *name);
char *           athd_job_type_to_str(athd_job_type type);
athd_job_type    athd_job_type_from_str(const char *type);
apr_status_t     athd_job_set_mail_on(athd_job *job, int flag);
apr_status_t     athd_job_add_mailaddr(athd_job *job, const char *addr);
apr_status_t     athd_job_set_mailreplyto(athd_job *job, const char *addr);
apr_status_t     athd_job_add_engine(athd_job *job, athd_engine *engine);
apr_status_t     athd_job_push_response(athd_request *request);
athd_request *   athd_job_shift_response(athd_job *job);
apr_status_t     athd_job_lock(athd_job *job);
apr_status_t     athd_job_unlock(athd_job *job);
char *           athd_job_to_str(apr_pool_t *pool, athd_job *job);

/* engine.c */
athd_engine *    athd_engine_create(apr_pool_t *pool, const char *name);
void             athd_engine_destroy(athd_engine **engine);
void             athd_engine_cache_init(apr_pool_t *pool);
athd_engine *    athd_engine_add_by_name(athd_conf *conf, const char *name);
athd_engine *    athd_engine_for_name(ath_list *engines, const char *name);
apr_status_t     athd_engine_set_url(athd_engine *engine, const char *url);
apr_status_t     athd_engine_push_req(athd_request *req);
athd_request *   athd_engine_shift_req(athd_engine *engine);
int              athd_engine_req_qsize(athd_engine *engine);
apr_status_t     athd_engine_new_connection(athd_engine *engine);
char *           athd_engine_to_str(apr_pool_t *pool, athd_engine *engine);
ath_phys *       athd_engine_phys_map_set(athd_engine *eng, 
					  const ath_phys *physsrc);
ath_farm *       athd_engine_farm_map_set(athd_engine *eng, 
					  const ath_farm *farmsrc);
ath_farm *       athd_engine_farm_map_get(athd_engine *eng, const char *name);

/* connection.c */
apr_status_t     athd_connection_shared_setup(apr_pool_t *pool);
apr_status_t     athd_connection_create(athd_connection **conn, 
					const apr_uri_t *uri, 
					apr_pool_t *pool);
void             athd_connection_acquire(athd_connection *conn);
void             athd_connection_release(athd_connection **conn);
void             athd_connection_retire(athd_connection *conn);
int              athd_connection_is_retired(athd_connection *conn);
apr_status_t     athd_connection_do_serf(athd_request *req);
void             athd_connection_reset(int sig);

/* config.c */
athd_conf *      athd_conf_create(apr_pool_t *pool, 
				  const char *str_path,
				  const athd_conf_prop *props);
void             athd_conf_destroy(athd_conf **conf);
athd_conf *      athd_conf_overrides(athd_conf *conf, 
				     const athd_conf_prop *props,
				     ath_list *propovers);
void             athd_conf_current_set(athd_conf *conf);
athd_conf *      athd_conf_current_get();
char *           athd_conf_to_str(apr_pool_t *pool, athd_conf *conf);
const char *     athd_conf_prop_set(athd_conf *conf, 
				    const athd_conf_prop *prop, 
				    char *arg, char *pararg);
const athd_conf_prop * athd_conf_prop_get(const athd_conf_prop *props, 
				    char *cmd, char *parcmd);
athd_ip_farm *   athd_conf_ip_farm_add(athd_conf *conf, const char *name, 
				       int farmport, int physport);

/* props.c (config properties)                          */
/* require params: athd_conf *, char * arg              */
/* optional (NULL ok) param: char *parg --              */
/*     parg is the argument passed to the prop's parent */
const char * athd_conf_prop_name(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_debug(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_shm(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_apconf(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_uid(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_gid(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_port(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_pidfile(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_logfile(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_loglock(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_shell(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_sendmail(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_ip(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_ipport(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_ipdeny(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_ipsock(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_ipmapfarm(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_ipfarms(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_statspulse(athd_conf *conf, char *arg, char *parg);
const char * athd_conf_prop_eng(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_engkeep(athd_conf *conf, char *arg, char *parg);
const char * athd_conf_prop_engqlimit(athd_conf *conf, char *arg, char *parg);
const char * athd_conf_prop_engpri(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_engsec(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_engip(athd_conf *conf, char *arg, char *parg);
const char * athd_conf_prop_job(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_jobtype(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_jobfreq(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_jobmail(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_jobmailaddr(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_jobmailreply(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_jobmailrate(athd_conf *cf, char *arg, char *parg);
const char * athd_conf_prop_jobeng(athd_conf *conf, char *arg, char *parg);

/* log.c */
apr_status_t     athd_log_init(apr_pool_t *pglobal);
void             athd_log_set_lvl(int lvl);
const char *     athd_log_get_strlvl();
apr_status_t     athd_log_write_str(const char *str);
apr_status_t     athd_log(int lvl, const char *fmt, ...);
apr_status_t     athd_log_err(int lvl, apr_status_t stat, const char *fmt, ...);
apr_status_t     athd_logv(int lvl, const char *fmt, va_list args);
char *           athd_log_time(apr_pool_t *pool);

/* stats.c */
apr_status_t     athd_stats_setup(apr_pool_t *pglobal);
float            athd_stats_get_by_type(char type);
void             athd_stats_set_by_type(char type, float val);
void             athd_stats_upd_phys(ath_upd_phys *phys);
apr_status_t     athd_stats_refresh();

/* cmd_req.c */
athd_cmd_req *   athd_cmd_req_create(apr_pool_t *pool, 
				     athd_cmd_handler *handler);

/* cmd_handler.c */
void             athd_cmd_handler_shared_setup(apr_pool_t *pgobal);
athd_cmd_handler * athd_cmd_handler_create(apr_pool_t *pool);
int              athd_cmd_handler_sessions_active();
int             athd_cmd_handler_sessions_total();
int             athd_cmd_handler_requests_total();

/* cmd_io.c */
apr_status_t     athd_cmd_io_accept(athd_cmd_handler *handler, 
				    apr_socket_t *socket);
apr_status_t     athd_cmd_io_recv_str(athd_cmd_req *req, char **str);
apr_status_t     athd_cmd_io_send_add(athd_cmd_req *req, const char *buf);
apr_status_t     athd_cmd_io_send_flush(athd_cmd_req *req);
apr_status_t     athd_cmd_io_send_str(athd_cmd_handler *handler,
				      const char *str);

/* cmd_parser.c */
athd_cmd_act     athd_cmd_parser(athd_cmd_req *req, char *cursor);
apr_status_t     athd_cmd_parser_prompter(athd_cmd_req *req);
/* job_thread.c */
void *           athd_job_thread_monitor(void *job_ctx);
void             athd_job_thread_shared_setup(apr_pool_t *pool);
void *           athd_job_thread_mirror(void *job_ctx);
void *           athd_job_thread_agent(void *job_ctx);


/* engine_thread.c */
void *           athd_engine_thread(void *engine_ctx);
void             athd_engine_thread_shared_setup(apr_pool_t *pglobal);

/* mail_thread.c */
void *           athd_mail_thread(void *conf_ctx);
void             athd_mail_queque_add(athd_mail *mail);
apr_status_t     athd_mail_thread_setup(apr_pool_t *pglobal);

/* lb_thread.c */
void *           athd_lb_thread(void *conf_ctx);
apr_status_t     athd_lb_thread_setup(apr_pool_t *pglobal);

/* stats_thread.c */
apr_status_t     athd_stats_thread_setup(apr_pool_t *pglobal);
void *           athd_stats_thread(void *conf_ctx);

/* listen_thread.c */
void *           athd_listen_thread(void *conf_ctx);
apr_status_t     athd_listen_thread_setup(apr_pool_t *pool);

/* watchdog_thread.c */
pthread_t *      athd_watchdog_thread_setup(apr_pool_t *pool);
void *           athd_watchdog_thread(void *noctx);
void             athd_sig_handler_register(athd_sig_func func, 
					   const char *name, int runlvl);

#endif /* ATHD_D */
 
